//========================================================================
//  SE5 AI Orders - Planets - Captain Kwok's Balance Mod v125+
//========================================================================
//
//  1. Determine our colony's unit needs Fx[Colony_Unit_Needs]
//  2. Optimize planet populations to undome planets Fx[Scrap_Population]
//  3. Maintain population happiness Fx[Keep_Population_Happy]
//  4. Manage colony output by adding/modifying facilities Fx[Increase_Colony_Output]
//  5. Convert resources Fx[Convert_Resources]
//  6. Launch/recover fighters Fx[Launch_Fighters]
//  7. Launch/recover satellites Fx[Launch_Satellites]
//  8. Launch/recover drones Fx[Launch_Drones]
//  9. Launch/recover mines Fx[Launch_Mines]
// 10. Scrap obsolete units Fx[Scrap_Obsolete_Units]
//
// Balance Mod Changes:
// --------------------
// v1.29 Fixed   - Fx[Scrap_Population] was not removing non-breathing populations due to an error in the determination of a planet's atmosphere
//       Changed - In asteroid systems (or limited planet systems) AI will replace facilities to ensure a resupply depot and then a space yard is present
//       Changed - In emergency resource situations, AI players will consider scrapping research or intel facilities (limited)
//       Changed - Planets were not gated by the minister toggle control (v129a)
// v1.25 Added   - Additional conditions for Interdimensional racial facilities
//       Added   - Better conditions for adding climate control facility to polluted planet
// v1.21 Fixed   - Removed Anti-Planet Drone reference from planet drone launching routine in Fx[Launch_Drones]
//       Fixed   - Removed extra check for temporal space yard facility as the condition already checks for the space yard ability Fx[Increase_Colony_Output]
// v1.20 Fixed   - AI players would sometimes add multiple Value Improvement Plants
//       Fixed   - AI players would sometimes add multiple Planetary Gravitational Facilities
// v1.19 Added   - AI will increase their storage capacity for a resource if they have a large surplus and current storage levels are high
//       Fixed   - The AI would sometimes add an Atmospheric Modification Planet to convert a Gas Giant to a None atmosphere (v1.19a)
//       Changed - The AI won't bother with recovering mines (v1.19a)
//       Changed - Revised Fx[Increase_Colony_Output] to make improvements in facility selections for scrap and replace scheme (v1.19b)
//       Changed - Further improvements to Fx[Increase_Colony_Output] (v1.19c)
//       Fixed   - AI empires were not obeying sector limits for units when launched from planets (v1.19c)
//       Fixed   - Sometimes the AI would add Intelligence facilities in a non-Intel game (v1.19c)
//       Fixed   - Fx[Increase_Colony_Output] allowed the AI to build multiple Robotoid Factory facilities on a planet (v1.19d)
//       Fixed   - Error in Fx[Scrap_Obsolete_Units] that caused an AI empire to self-destruct! (v1.19f)
//       Changed - Made improvements to the AI's use of Resource Converters (v1.19g)
//       Changed - AI's unit scrapping is now better distributed across its colonies (v1.19h)
//       Changed - Allow the AI to add troops directly to planet queues when affecting by low happiness (v1.19h)
//       Changed - Reduced AI's frequency of swapping Research for Intel facilities (and vice versa) (v1.19h)
//       Changed - Improved AI's recognition of when a Spaceport, Space Yard, or Resupply Depot was suddenly required (v1.19i)
//       Changed - Added support for finite resource games and AI scrap facility routine (v1.19j)
//       Changed - Made improvements in the AI's convert resources routine (v1.19j)
//       Changed - Improvements to the Fx[Increase_Colony_Output] (v1.19j)
// v1.17 Fixed   - Error in Fx[Scrap_Facility] that sometimes resulted in a facility not being scrapped
// v1.15 Fixed   - Several errors in scrap function to replace a non-resource facility with a resource facility
//       Added   - Fx[Convert_Resources] to convert resources for the AI (Workaround function)
//       Fixed   - The AI wasn't scrapping population correctly when 3 or more races were present
//       Added   - Expanded facility scrap and replace to include Value Improvement plants, Atmosphere Converters etc.
// v1.14 Added   - AI will scrap a non-resource facility to build a resource facility if low on that resource
// v1.13 Changed - AI colonies will only launch fighter or drone groups in defense system locations
//       Changed - AI will scrap planet improvement facilities when appropriate
//       Added   - Planets will sometimes recover units to allow for the scrapping of obsolete units
//       Changed - Improved conditions for scrapping obsolete units
//       Removed - Fx[Fix_Environmental_Effects]
// v1.12 Changed - Planets in defense locations will launch mines more frequently and in larger numbers
//       Added   - AI will scrap research facilities if at max tech
// v1.11 Added   - Debug routine to print out happiness levels for all planets
//       Changed - AI will hold onto more units in cargo since planet's will launch them automatically in combat
// v1.10 Changed - Increased size of unit groups that the AI launches
// v1.07 Fixed   - AI was sometimes scrapping facilities for modifier facilities they didn't have yet
// v1.06 Changed - AI will stockpile units more frequently and launch in larger groups
//       Changed - AI will not launch Anti-Planet Drones
//       Added   - New Fx[Scrap_Population] to remove non-breathers when breathers are present
//       Added   - New Fx[Increase_Colony_Output] to add modifier facilities to colonies
//       Added   - New Fx[Scrap_Facility] to scrap facilities when space is needed for new ones
//       Changed - Updated names of Ministers responsible for various functions
// v1.04 Changed - Fx[Scrap_Obsolete_Units] will also scrap obsolete satellites in cargo
// v1.03 Added   - Fx[Scrap_Obsolete_Units] to scrap obsolete Weapon Platforms
// v1.02 Fixed   - Typo in [Fx]Launch_Planetary_Drones
// v1.00 Added   - Implemented [Fx]Launch_Planetary_Drones
// v0.92 Added   - Implemented [Fx]Launch_Planetary_Fighters
//
// Balance Mod To-do list:
// -----------------------
// - Nothing pending
//
// Script Function Requests:
// -------------------------
// - Sys_Order_Convert_Resources(sobj_id, to_resource_type, from_resource_type, from_resource_amt) : boolean (Returns TRUE if conversion successful)
// - Sys_Set_Space_Object_Cargo_Item_Population_Loyalty(sobj_id, cargo_item_id) : boolean (Returns TRUE is set successful)
// - Sys_Is_Native_Race(plr_id, sobj_id, cargo_item_id) : boolean (Returns TRUE if set successful)

//------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------

globalvars

  gbl_facility_scrapped:               boolean := FALSE
  gbl_max_facilities_scrapped:         boolean := FALSE

endglobalvars

//------------------------------------------------------------------------
// Forward Declarations
//------------------------------------------------------------------------

deffunc

function Colony_Unit_Needs returns boolean
params
  planet_id:                 long
end

function Keep_Population_Happy returns boolean
params
  planet_id:                 long
end

function Convert_Resources returns boolean
params
  planet_id:                 long
end

function Increase_Colony_Output returns boolean
params
  planet_id:                 long
end

function Scrap_Facility returns boolean
params
  planet_id:                 long
  facil_id:                  long
  add_non_resource_facility: boolean
end

function Scrap_Population returns boolean
params
  planet_id:                 long
end

function Launch_Planetary_Fighters returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
end

function Launch_Planetary_Satellites returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
end

function Launch_Planetary_Mines returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
end

function Launch_Planetary_Drones returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
end

function Scrap_Obsolete_Units returns boolean
params
  planet_id:                 long
end

enddeffunc

//------------------------------------------------------------------------
// AI_Orders_Planets
//------------------------------------------------------------------------
function AI_Orders_Planets returns boolean
vars
  planet_count:              long
  planet_index:              long
  planet_id:                 long
  planet_name:               string
  planet_atmosphere:         string
  planet_colony_type:        string
  planet_sys_loc:            long
  enemy_present:             boolean := FALSE
  minister_controlled:       boolean := FALSE
begin

  // Get the number of our colonies
  set planet_count := lst_AI_Our_Colonies.count()

  // Debug output
  call Sys_Debug_Print("Planets", "--------------")
  call Sys_Debug_Print("Planets", "Planet Orders:")

  if (planet_count > 0) then
    for planet_index := 1 to planet_count do
      set planet_id := lst_AI_Our_Colonies.get(planet_index)
      set planet_name := Sys_Get_Space_Object_Name(planet_id)
      set planet_colony_type := Sys_Get_Planet_Colony_Type(planet_id)
      set planet_sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
      set enemy_present := Is_Enemy_Present_In_System(planet_sys_loc)
      set minister_controlled := Sys_Get_Space_Object_Minister_Controlled(planet_id)

      // Debug output
      call Sys_Debug_Print("Planets", "  - " + planet_name + " (" + planet_colony_type + ")")
      call Sys_Debug_Print("Planets", "    - Structure = " + Sys_Convert_Long_To_String(Sys_Get_Space_Object_Total_Tonnage_Structure(planet_id)))
      call Sys_Debug_Print("Planets", "    - Armor = " + Sys_Convert_Long_To_String(Sys_Get_Space_Object_Current_Armor_Structure(planet_id)))
      call Sys_Debug_Print("Planets", "    - Shields = " + Sys_Convert_Long_To_String(Sys_Get_Space_Object_Current_Shields(planet_id)))
      call Sys_Debug_Print("Planets", "    - Weapon Damage = " + Sys_Convert_Long_To_String(Sys_Get_Space_Object_Total_Weapon_Damage(planet_id)))
      // Are enemies present?
      If (enemy_present) then
        call Sys_Debug_Print("Planets", "    - Enemy Present!")
      endif

      // Note our colony's unit needs
      call Colony_Unit_Needs(planet_id)
      // Give orders to Minister-controlled planets only
      if (minister_controlled) then
        // Debug output
        call Sys_Debug_Print("Planets", "    - Minister Controlled")
        // Manage our colony's population
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Population") then
          call Scrap_Population(planet_id)
        endif
        // Manage our colony's facilities
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Facilities") then
          call Keep_Population_Happy(planet_id)
          call Increase_Colony_Output(planet_id)
        endif
        // Manage our resource conversion
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Resource Conversion") then
          call Convert_Resources(planet_id)
        endif
        // Manage our colony's fighters
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Fighter Launching") then
          call Launch_Planetary_Fighters(planet_id, enemy_present)
        endif
        // Manage our colony's satellites
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Satellite Launching") then
          call Launch_Planetary_Satellites(planet_id, enemy_present)
        endif
        // Manage our colony's drones
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Drone Launching") then
          call Launch_Planetary_Drones(planet_id, enemy_present)
        endif
        // Manage our colony's mines
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Mine Launching") then
          call Launch_Planetary_Mines(planet_id, enemy_present)
        endif
        // Manage our colony's unit scrapping
        if Sys_Using_AI_Minister(sys_long_Player_ID, "Colonies - Unit Scrapping") then
          call Scrap_Obsolete_Units(planet_id)
        endif
      endif
    endfor
  endif

  // Sort our colonies with low units in order of most units wanted
  // Troops
  call Sys_Prepare_For_List_Sort()
  call Sys_Set_List_Sort_Field(1, lst_AI_Colony_Low_Troops)
  call Sys_Set_List_Sort_Field(2, lst_AI_Colony_Num_Troops_Wanted)
  call Sys_Add_List_Sort_Sort_Column(2, FALSE)
  call Sys_Execute_List_Sort()

  // Fighters
  call Sys_Prepare_For_List_Sort()
  call Sys_Set_List_Sort_Field(1, lst_AI_Colony_Low_Fighters)
  call Sys_Set_List_Sort_Field(2, lst_AI_Colony_Num_Fighters_Wanted)
  call Sys_Add_List_Sort_Sort_Column(2, FALSE)
  call Sys_Execute_List_Sort()

  // Satellites
  call Sys_Prepare_For_List_Sort()
  call Sys_Set_List_Sort_Field(1, lst_AI_Colony_Low_Satellites)
  call Sys_Set_List_Sort_Field(2, lst_AI_Colony_Num_Satellites_Wanted)
  call Sys_Add_List_Sort_Sort_Column(2, FALSE)
  call Sys_Execute_List_Sort()

  // Weapon Platforms
  call Sys_Prepare_For_List_Sort()
  call Sys_Set_List_Sort_Field(1, lst_AI_Colony_Low_Weapon_Platforms)
  call Sys_Set_List_Sort_Field(2, lst_AI_Colony_Num_Weapon_Platforms_Wanted)
  call Sys_Add_List_Sort_Sort_Column(2, FALSE)
  call Sys_Execute_List_Sort()

  // Mines
  call Sys_Prepare_For_List_Sort()
  call Sys_Set_List_Sort_Field(1, lst_AI_Colony_Low_Mines)
  call Sys_Set_List_Sort_Field(2, lst_AI_Colony_Num_Mines_Wanted)
  call Sys_Add_List_Sort_Sort_Column(2, FALSE)
  call Sys_Execute_List_Sort()

  // Drones
  call Sys_Prepare_For_List_Sort()
  call Sys_Set_List_Sort_Field(1, lst_AI_Colony_Low_Drones)
  call Sys_Set_List_Sort_Field(2, lst_AI_Colony_Num_Drones_Wanted)
  call Sys_Add_List_Sort_Sort_Column(2, FALSE)
  call Sys_Execute_List_Sort()

end

//------------------------------------------------------------------------
// Colony_Unit_Needs
//------------------------------------------------------------------------
function Colony_Unit_Needs returns boolean
params
  planet_id:                 long
vars
  planet_size:               long
  planet_sys_loc:            long
  planet_sect_loc:           long
  planet_colony_type:        string
  num_facilities:            long
  num_units:                 long
  wanted_units:              long
  min_units:                 long
  max_units:                 long
  min_unit_mod:              long := 1
  max_unit_mod:              long := 1
  is_core_colony:            boolean := FALSE
  is_capital_colony:         boolean := FALSE
  is_border_colony:          boolean := FALSE
  is_defense_colony:         boolean := FALSE
  is_unit_hub:               boolean := FALSE
  is_space_yard_hub:         boolean := FALSE
  is_fleet_hub:              boolean := FALSE
  unit_flag:                 string := ""
begin

  // Get our planet's details
  set planet_size := Get_Planet_Size(planet_id)
  set planet_sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
  set planet_sect_loc := Sys_Get_Space_Object_Sector_Location(planet_id)
  set planet_colony_type := Sys_Get_Planet_Colony_Type(planet_id)
  set num_facilities := Get_Total_Number_Of_Facilities_On_Planet(planet_id)

  // Set our colony flags for unit modifiers
  set is_core_colony := (lst_AI_Our_Core_Colonies.indexof(planet_id) > 0)
  set is_capital_colony := (lst_AI_Our_System_Capital_Colonies.indexof(planet_id) > 0)
  set is_border_colony := (lst_AI_Border_System.indexof(planet_sys_loc) > 0)
  set is_defense_colony := (lst_AI_Defense_Location_System.indexof(planet_sys_loc) > 0)
  set is_space_yard_hub := (lst_AI_Our_Space_Yards.indexof(planet_id) > 0)
  set is_fleet_hub := (lst_AI_Our_Fleet_Hubs.indexof(planet_id) > 0)
  // Identify colonies suitable for unit hubs
  set is_unit_hub := (is_space_yard_hub) and ((is_core_colony) or (is_capital_colony)) and ((is_border_colony) or (is_defense_colony))

  // Debug output
  if (is_capital_colony) then
    call Sys_Debug_Print("Planets", "    - System Capital")
  endif
  if (is_core_colony) then
    call Sys_Debug_Print("Planets", "    - Core Colony")
  endif
  if (is_border_colony) then
    call Sys_Debug_Print("Planets", "    - Border Colony")
  endif
  if (is_defense_colony) then
    call Sys_Debug_Print("Planets", "    - Defense Colony")
  endif
  if (is_space_yard_hub) then
    call Sys_Debug_Print("Planets", "    - Space Yard Hub")
  endif
  if (is_fleet_hub) then
    call Sys_Debug_Print("Planets", "    - Fleet Hub")
  endif
  if (is_unit_hub) then
    call lst_AI_Our_Colony_Unit_Hubs.add(planet_id)
    call Sys_Debug_Print("Planets", "    - Unit Hub")
  endif

  // Set our unit modifiers
  if (is_core_colony) or (is_capital_colony) then
    set max_unit_mod := max_unit_mod + 1
  endif
  if (is_border_colony) or (is_defense_colony) then
    set min_unit_mod := min_unit_mod + 1
    set max_unit_mod := max_unit_mod + 1
  endif
  if (is_unit_hub) then
    set min_unit_mod := min_unit_mod + 1
    set max_unit_mod := max_unit_mod + 2
  endif

  // Debug output
  call Sys_Debug_Print("Planets", "    - Units Wanted:")
  call Sys_Debug_Print("Planets", "      - Min Unit Mod = " + Sys_Convert_Long_To_String(min_unit_mod) + "; Max Unit Mod = " + Sys_Convert_Long_To_String(max_unit_mod))

  // Troops
  if (bool_Race_Uses_Troops) then
    set unit_flag := ""
    set num_units := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Troop")
    set min_units := planet_size * 5 * min_unit_mod
    set max_units := Sys_Trunc((lng_Num_Troops + lng_Num_Light_Troops + lng_Num_Heavy_Troops) * num_facilities / 1000 * lng_AI_Pct_Troops_For_Colonies / 100 * max_unit_mod)
    set wanted_units := Sys_Max_Long(min_units, max_units)
    // If low on troops, add to our list of colonies needing troops
    if (num_units < wanted_units) then
      call lst_AI_Colony_Low_Troops.add(planet_id)
      call lst_AI_Colony_Num_Troops_Wanted.add(wanted_units - num_units)
      set unit_flag := "*"
    endif
    if (num_units > (wanted_units * 2)) then
      call lst_AI_Colony_High_Troops.add(planet_id)
      set unit_flag := "!"
    endif
    // Debug output
    call Sys_Debug_Print("Planets", "      - Troops" + unit_flag + " (" + Sys_Convert_Long_To_String(num_units) + "/" + Sys_Convert_Long_To_String(wanted_units) + ")")
  endif

  // Fighters
  if (bool_Race_Uses_Fighters) then
    set unit_flag := ""
    set num_units := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Fighter") + Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Fighter", planet_sys_loc, planet_sect_loc)
    set min_units := planet_size * 2 * min_unit_mod
    set max_units := Sys_Trunc((lng_Num_Fighters + lng_Num_Fighter_Bombers + lng_Num_Kamikaze_Fighters) * num_facilities / 1000 * lng_AI_Pct_Fighters_For_Colonies / 100 * max_unit_mod)
    set wanted_units := Sys_Max_Long(min_units, max_units)
    // Don't bother with fighters if the colony wanted amount is below our minimum fighter group size
    if (max_units < lng_AI_Min_Fighter_Group_Size) then
      set wanted_units := 0
    endif
    // If low on fighters, add to our list of colonies needing fighters
    if (num_units < wanted_units) then
      call lst_AI_Colony_Low_Fighters.add(planet_id)
      call lst_AI_Colony_Num_Fighters_Wanted.add(wanted_units - num_units)
      set unit_flag := "*"
    endif
    if (num_units > (wanted_units * 2)) then
      call lst_AI_Colony_High_Fighters.add(planet_id)
      set unit_flag := "!"
    endif
    // Debug output
    call Sys_Debug_Print("Planets", "      - Fighters" + unit_flag + " (" + Sys_Convert_Long_To_String(num_units) + "/" + Sys_Convert_Long_To_String(wanted_units) + ")")
  endif

  // Weapon Platforms
  if (bool_Race_Uses_Weapon_Platforms) then
    set unit_flag := ""
    set num_units := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Weapon Platform")
    set min_units := 1 + Sys_Divide_Long(planet_size, 2)
    set max_units := planet_size + Sys_Divide_Long(num_facilities, 5)
    // Special conditions for weapon platforms only
    if (not is_defense_colony) or (not is_border_colony) then
      set max_units := Sys_Divide_Long(max_units, 2)
      set max_units := Sys_Max_Long(min_units, max_units)
    endif
    // Set the number of wanted platforms
    set wanted_units := Sys_Max_Long(min_units, max_units)
    // If low on weapon platforms, add to our list of colonies needing weapon platforms
    if (num_units < wanted_units) then
      call lst_AI_Colony_Low_Weapon_Platforms.add(planet_id)
      call lst_AI_Colony_Num_Weapon_Platforms_Wanted.add(wanted_units - num_units)
      set unit_flag := "*"
    endif
    if (num_units > (wanted_units * 2)) then
      call lst_AI_Colony_High_Weapon_Platforms.add(planet_id)
      set unit_flag := "!"
    endif
    // Debug output
    call Sys_Debug_Print("Planets", "      - Weapon Platforms" + unit_flag + " (" + Sys_Convert_Long_To_String(num_units) + "/" + Sys_Convert_Long_To_String(wanted_units) + ")")
  endif

  // Satellites
  if (bool_Race_Uses_Satellites) then
    set unit_flag := ""
    set min_units := planet_size * min_unit_mod
    set num_units := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Satellite") + Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Satellite", planet_sys_loc, planet_sect_loc)
    set max_units := Sys_Trunc((lng_Num_Satellites + lng_Num_PD_Sats + lng_Num_Seeker_Sats + lng_Num_Recon_Sats + lng_Num_Repair_Sats) * num_facilities / 1000 * lng_AI_Pct_Satellites_For_Colonies / 100 * max_unit_mod)
    set wanted_units := Sys_Max_Long(min_units, max_units)
    // Don't bother with satellites if the colony wanted amount is below our minimum satellite group size
    if (wanted_units < lng_AI_Min_Satellite_Group_Size) then
      set wanted_units := 0
    endif
    // If low on satellites, add to our list of colonies needing satellites
    if (num_units < wanted_units) then
      call lst_AI_Colony_Low_Satellites.add(planet_id)
      call lst_AI_Colony_Num_Satellites_Wanted.add(wanted_units - num_units)
      set unit_flag := "*"
    endif
    if (num_units > (wanted_units * 2)) then
      call lst_AI_Colony_High_Satellites.add(planet_id)
      set unit_flag := "!"
    endif
    // Debug output
    call Sys_Debug_Print("Planets", "      - Satellites" + unit_flag + " (" + Sys_Convert_Long_To_String(num_units) + "/" + Sys_Convert_Long_To_String(wanted_units) + ")")
  endif

  // Mines
  if (bool_Race_Uses_Mines) then
    set unit_flag := ""
    set num_units := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Mine") + Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Mine", planet_sys_loc, planet_sect_loc)
    set min_units := planet_size * 10 * min_unit_mod
    set max_units := Sys_Trunc(lng_Num_Mines * num_facilities / 1000 * lng_AI_Pct_Mines_For_Colonies / 100 * max_unit_mod)
    set wanted_units := Sys_Max_Long(min_units, max_units)
    // Don't bother with mines if the colony wanted amount is below our minimum satellite group size
    if (max_units < lng_AI_Min_Mine_Group_Size) then
      set wanted_units := 0
    endif
    // If low on mines, add to our list of colonies needing mines
    if (num_units < wanted_units) then
      call lst_AI_Colony_Low_Mines.add(planet_id)
      call lst_AI_Colony_Num_Mines_Wanted.add(wanted_units - num_units)
      set unit_flag := "*"
    endif
    if (num_units > (wanted_units * 2)) then
      call lst_AI_Colony_High_Mines.add(planet_id)
      set unit_flag := "!"
    endif
    // Debug output
    call Sys_Debug_Print("Planets", "      - Mines" + unit_flag + " (" + Sys_Convert_Long_To_String(num_units) + "/" + Sys_Convert_Long_To_String(wanted_units) + ")")
   endif

  // Drones
  if (bool_Race_Uses_Drones) then
    set unit_flag := ""
    set num_units := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Drone") + Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Drone", planet_sys_loc, planet_sect_loc)
    set min_units := planet_size * min_unit_mod
    set max_units := Sys_Trunc((lng_Num_Atk_Drones + lng_Num_Def_Drones + lng_Num_Kamikaze_Drones + lng_Num_Bombardment_Drones) * num_facilities / 1000 * lng_AI_Pct_Drones_For_Colonies / 100 * max_unit_mod)
    set wanted_units := Sys_Max_Long(min_units, max_units)
    // Don't bother with drones if the colony is small
    if (wanted_units < lng_AI_Min_Drone_Group_Size) then
      set wanted_units := 0
    endif
    // If low on drones, add to our list of colonies needing drones
    if (num_units < wanted_units) then
      call lst_AI_Colony_Low_Drones.add(planet_id)
      call lst_AI_Colony_Num_Drones_Wanted.add(wanted_units - num_units)
      set unit_flag := "*"
    endif
    if (num_units > (wanted_units * 2)) then
      call lst_AI_Colony_High_Drones.add(planet_id)
      set unit_flag := "!"
    endif
    // Debug output
    call Sys_Debug_Print("System", "      - Drones" + unit_flag + " (" + Sys_Convert_Long_To_String(num_units) + "/" + Sys_Convert_Long_To_String(wanted_units) + ")")
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Keep_Population_Happy
//------------------------------------------------------------------------
function Keep_Population_Happy returns boolean
params
  planet_id:                 long
vars
  planet_happiness:          long
  planet_index:              long
  cargo_item_count:          long
  cargo_index:               long
  cargo_item_id:             long
  pop_happiness:             long
  pop_loyalty:               long
  troop_design_id:           long
  num_troops_wanted:         long
begin

  // Get our planet's details
  set pop_happiness := Sys_Get_Planet_Happiness(planet_id)

  // Debug output
  call Sys_Debug_Print("Planets", "    - Happiness is " + Sys_Convert_Long_To_String(pop_happiness))

  // Check our planet's population groups to get their loyalty
  set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)
  if (cargo_item_count > 0) then
    for cargo_index := 1 to cargo_item_count do
      set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
      // Get the population's loyalty
      if (Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id) = CARGO_ITEM_TYPE_POPULATION) then
        set pop_loyalty := Sys_Get_Space_Object_Cargo_Item_Population_Loyalty(planet_id, cargo_item_id)
        // Debug output
        call Sys_Debug_Print("Planets", "    - Loyalty is " + Sys_Convert_Long_To_String(pop_loyalty))
      endif
    endfor
  endif

  // If the population happiness is poor, attempt to immediately add troops to the queue
  if (pop_happiness > 0) and (pop_happiness <= 50) and (not bool_Race_Minerals_Low) then
    set planet_index := lst_AI_Colony_Low_Troops.indexof(planet_id)
    
    if (planet_index > 0) and (Sys_Get_Construction_Queue_Item_Count(planet_id) < 1) then
      // Find latest troop design
      set troop_design_id := Sys_Get_Latest_Vehicle_Design_Of_AI_Type(sys_long_Player_ID, "Light Troop")
      // If no Light Troop design type
      if (troop_design_id = 0) then
        set troop_design_id := Sys_Get_Latest_Vehicle_Design_Of_AI_Type(sys_long_Player_ID, "Troop")
      endif
      // Check to add Troops of our most recent design to the colony
      if (troop_design_id > 0) then
        set num_troops_wanted := Sys_Min_Long(lst_AI_Colony_Num_Troops_Wanted.get(planet_index), 10)
        // Add the troops to our planet's queue
        if (num_troops_wanted > 0) then
          call Sys_Add_Vehicle_Design_To_Construction_Queue(planet_id, troop_design_id, num_troops_wanted)
          // Debug output
          call Sys_Debug_Print("Planets", "    - Added troops (" + Sys_Convert_Long_To_String(num_troops_wanted) + ") to its queue to prevent riots")
        endif
      endif
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Convert_Resources
//------------------------------------------------------------------------
function Convert_Resources returns boolean
params
  planet_id:                 long
vars
  planet_name:               string
  planet_sys_loc:            long
  planet_sect_loc:           long
  sys_name:                  string
  has_converter:             boolean := FALSE
  new_minerals:              long
  new_organics:              long
  new_radioactives:          long
  tech_level:                long
  max_to_convert:            long
  conversion_pct:            long
  conversion_type:           string
  to_convert_amt:            long
  from_convert_amt:          long
  from_resource_amt:         string
  from_resource_type:        string
  to_resource_amt:           string
  to_resource_type:          string
  msg_text:                  string
begin

  // Get our planet's details
  set planet_name := Sys_Get_Space_Object_Name(planet_id)
  set planet_sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
  set planet_sect_loc := Sys_Get_Space_Object_Sector_Location(planet_id)
  set sys_name := Sys_Get_Solar_System_Name(planet_sys_loc)

  // Does the planet have a resource converter?
  set has_converter := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_resource_conversion)

  if (has_converter) then
    // Get our stored resources
    set tech_level := Sys_Get_Highest_Facility_Level(sys_long_Player_ID, lng_facility_id_resource_conversion)
    set conversion_pct := 55 + (tech_level * 5)

    // Which type of resource conversion should we attempt?
    // Minerals
    if (bool_Race_Minerals_Low) or (bool_Race_Minerals_Adequate) or (lng_Minerals_Deficit > 5000) then
      if (lng_Max_Organics_To_Convert > lng_Max_Radioactives_To_Convert) then
        set conversion_type := "Organics to Minerals"
      else
        set conversion_type := "Radioactives to Minerals"
      endif
    endif
    // Organics
    if (bool_Race_Organics_Low) or (bool_Race_Organics_Adequate) or (lng_Organics_Deficit > 5000) then
      if (lng_Max_Radioactives_To_Convert > lng_Max_Minerals_To_Convert) then
        set conversion_type := "Radioactives to Organics"
      else
        set conversion_type := "Minerals to Organics"
      endif
    endif
    // Radioactives
    if (bool_Race_Radioactives_Low) or (bool_Race_Radioactives_Adequate) or (lng_Radioactives_Deficit > 5000) then
      if (lng_Max_Organics_To_Convert > lng_Max_Minerals_To_Convert) then
        set conversion_type := "Organics to Radioactives"
      else
        set conversion_type := "Minerals to Radioactives"
      endif
    endif

    // Determine the number of resources to convert
    case conversion_type
      "Organics to Minerals":
        set from_convert_amt := Sys_Min_Long(lng_Max_Organics_To_Convert, lng_Max_Minerals_Needed)
        set from_convert_amt := Sys_Divide_Long(from_convert_amt, 1000) * 1000
        set to_convert_amt := Sys_Trunc(from_convert_amt * conversion_pct / 100)
        set from_resource_type := "Organics"
        set from_resource_amt := Sys_Convert_Long_To_String(from_convert_amt)
        set to_resource_type := "Minerals"
        set to_resource_amt := Sys_Convert_Long_To_String(to_convert_amt)
        set new_minerals := to_convert_amt
        set new_organics := -from_convert_amt
        set lng_Max_Minerals_Needed := lng_Max_Minerals_Needed - to_convert_amt
        set lng_Max_Organics_To_Convert := lng_Max_Organics_To_Convert - from_convert_amt
      "Radioactives to Minerals":
        set from_convert_amt := Sys_Min_Long(lng_Max_Radioactives_To_Convert, lng_Max_Minerals_Needed)
        set from_convert_amt := Sys_Divide_Long(from_convert_amt, 1000) * 1000
        set to_convert_amt := Sys_Trunc(from_convert_amt * conversion_pct / 100)
        set from_resource_type := "Radioactives"
        set from_resource_amt := Sys_Convert_Long_To_String(from_convert_amt)
        set to_resource_type := "Minerals"
        set to_resource_amt := Sys_Convert_Long_To_String(to_convert_amt)
        set new_minerals := to_convert_amt
        set new_radioactives := -from_convert_amt
        set lng_Max_Minerals_Needed := lng_Max_Minerals_Needed - to_convert_amt
        set lng_Max_Radioactives_To_Convert := lng_Max_Radioactives_To_Convert - from_convert_amt
      "Radioactives to Organics":
        set from_convert_amt := Sys_Min_Long(lng_Max_Radioactives_To_Convert, lng_Max_Organics_Needed)
        set from_convert_amt := Sys_Divide_Long(from_convert_amt, 1000) * 1000
        set to_convert_amt := Sys_Trunc(from_convert_amt * conversion_pct / 100)
        set from_resource_type := "Radioactives"
        set from_resource_amt := Sys_Convert_Long_To_String(from_convert_amt)
        set to_resource_type := "Organics"
        set to_resource_amt := Sys_Convert_Long_To_String(to_convert_amt)
        set new_organics := to_convert_amt
        set new_radioactives := -from_convert_amt
        set lng_Max_Organics_Needed := lng_Max_Organics_Needed - to_convert_amt
        set lng_Max_Radioactives_To_Convert := lng_Max_Radioactives_To_Convert - from_convert_amt
      "Minerals to Organics":
        set from_convert_amt := Sys_Min_Long(lng_Max_Minerals_To_Convert, lng_Max_Organics_Needed)
        set from_convert_amt := Sys_Divide_Long(from_convert_amt, 1000) * 1000
        set to_convert_amt := Sys_Trunc(from_convert_amt * conversion_pct / 100)
        set from_resource_type := "Minerals"
        set from_resource_amt := Sys_Convert_Long_To_String(from_convert_amt)
        set to_resource_type := "Organics"
        set to_resource_amt := Sys_Convert_Long_To_String(to_convert_amt)
        set new_organics := to_convert_amt
        set new_minerals := -from_convert_amt
        set lng_Max_Organics_Needed := lng_Max_Organics_Needed - to_convert_amt
        set lng_Max_Minerals_To_Convert := lng_Max_Minerals_To_Convert - from_convert_amt
      "Organics to Radioactives":
        set from_convert_amt := Sys_Min_Long(lng_Max_Organics_To_Convert, lng_Max_Radioactives_Needed)
        set from_convert_amt := Sys_Divide_Long(from_convert_amt, 1000) * 1000
        set to_convert_amt := Sys_Trunc(from_convert_amt * conversion_pct / 100)
        set from_resource_type := "Organics"
        set from_resource_amt := Sys_Convert_Long_To_String(from_convert_amt)
        set to_resource_type := "Radioactives"
        set to_resource_amt := Sys_Convert_Long_To_String(to_convert_amt)
        set new_radioactives := to_convert_amt
        set new_organics := -from_convert_amt
        set lng_Max_Radioactives_Needed := lng_Max_Radioactives_Needed - to_convert_amt
        set lng_Max_Organics_To_Convert := lng_Max_Organics_To_Convert - from_convert_amt
      "Minerals to Radioactives":
        set from_convert_amt := Sys_Min_Long(lng_Max_Minerals_To_Convert, lng_Max_Radioactives_Needed)
        set from_convert_amt := Sys_Divide_Long(from_convert_amt, 1000) * 1000
        set to_convert_amt := Sys_Trunc(from_convert_amt * conversion_pct / 100)
        set from_resource_type := "Minerals"
        set from_resource_amt := Sys_Convert_Long_To_String(from_convert_amt)
        set to_resource_type := "Radioactives"
        set to_resource_amt := Sys_Convert_Long_To_String(to_convert_amt)
        set new_radioactives := to_convert_amt
        set new_minerals := -from_convert_amt
        set lng_Max_Radioactives_Needed := lng_Max_Radioactives_Needed - to_convert_amt
        set lng_Max_Minerals_To_Convert := lng_Max_Minerals_To_Convert - from_convert_amt
    endcase

    // Convert the resources
    if (from_convert_amt > 0) then
      set bool_Race_Converted_Resources := Sys_Change_Empire_Points(sys_long_Player_ID, new_minerals, new_organics, new_radioactives)
      // Log Message
      set msg_text := "Resource Minister: Our Colony on " + planet_name + " in system " + sys_name + " has converted " + from_resource_amt + " " + from_resource_type + " to " + to_resource_amt + " " + to_resource_type + "."
      call Sys_Add_Empire_Log_Entry(sys_long_Player_ID, planet_sys_loc, planet_sect_loc, "Resources Converted", msg_text, "Event_MoreCargoSpaceAvailable.jpg", "LargePortrait_Event_MoreCargoSpaceAvailable.jpg", LOG_TYPE_PERSONAL_NOTE, LOG_CATEGORY_TYPE_EMPIRE_NEWS, LOG_SUB_CATEGORY_TYPE_EMPIRE_MISC, 0)
      // Debug output
      call Sys_Debug_Print("Resources", "    - Converted " + Sys_Convert_Long_To_String(from_convert_amt) + " " + from_resource_type + " to " + Sys_Convert_Long_To_String(to_convert_amt) + " " + to_resource_type)
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Increase_Colony_Output
//------------------------------------------------------------------------
function Increase_Colony_Output returns boolean
params
  planet_id:                 long
vars
  planet_sys:                long
  planet_breathable:         boolean := FALSE
  planet_isolated:           boolean := FALSE
  planet_colony_type:        string
  planet_size:               string
  planet_num_facilities:     long
  planet_space_left:         long
  planet_conditions:         real
  planet_pollution_pts:      long
  planet_value:              resources
  planet_minerals:           real
  planet_organics:           real
  planet_radioactives:       real
  num_facilities:            long
  num_industrial_facilities: long
  num_spaceyards:            long
  num_factories:             long
  num_minerals:              long
  num_organics:              long
  num_radioactives:          long
  num_research:              long
  num_monolith:              long
  num_resource:              long
  num_intel:                 long
  planet_is_industrial:      boolean := FALSE
  skip_scrap_minerals:       boolean := FALSE
  skip_scrap_organics:       boolean := FALSE
  skip_scrap_radioactives:   boolean := FALSE
  skip_scrap_monolith:       boolean := FALSE
  skip_scrap_research:       boolean := FALSE
  skip_scrap_intel:          boolean := FALSE
  skip_spaceport:            boolean := TRUE
  skip_spaceyard:            boolean := TRUE
  skip_resupply:             boolean := TRUE
  skip_monolith:             boolean := TRUE
  skip_comp_factory:         boolean := TRUE
  skip_minerals_mod:         boolean := TRUE
  skip_organics_mod:         boolean := TRUE
  skip_radioactives_mod:     boolean := TRUE
  skip_research_mod:         boolean := TRUE
  skip_intel_mod:            boolean := TRUE
  skip_planet_atmosphere:    boolean := TRUE
  skip_planet_conditions:    boolean := TRUE
  skip_planet_value:         boolean := TRUE
  skip_shield_pts:           boolean := TRUE
  skip_ship_training:        boolean := TRUE
  skip_fleet_training:       boolean := TRUE
  skip_prod_mod:             boolean := TRUE
  skip_maint_mod:            boolean := TRUE
  skip_combat_mod:           boolean := TRUE
  skip_damage_mod:           boolean := TRUE
  skip_shield_mod:           boolean := TRUE
  skip_extra_space:          boolean := TRUE
  skip_dimensional_rift:     boolean := TRUE
  override_skip:             boolean := FALSE
  good_minerals:             boolean := FALSE
  good_organics:             boolean := FALSE
  good_radioactives:         boolean := FALSE
  good_resources:            boolean := FALSE
  facility_to_scrap:         long := 0
begin

  // Reset global scrap variable
  set gbl_facility_scrapped := FALSE

  // Get our planet's details
  set planet_sys := Sys_Get_Space_Object_System_Location(planet_id)
  set planet_size := Sys_Get_Planet_Size(planet_id)
  set planet_num_facilities := Get_Total_Number_Of_Facilities_On_Planet(planet_id)
  set planet_colony_type := Sys_Get_Planet_Colony_Type(planet_id)
  set planet_breathable := Is_Planet_Breathable_By_Population(planet_id)
  set planet_conditions := Sys_Get_Planet_Conditions(planet_id)
  set planet_pollution_pts := lst_AI_Colony_Pollution_Pts.get(lst_AI_Our_Colonies.indexof(planet_id))
  set planet_value := Sys_Get_Space_Object_Planet_Value(planet_id)
  set planet_minerals := planet_value.get(RESOURCE_TYPE_MINERALS)
  set planet_organics := planet_value.get(RESOURCE_TYPE_ORGANICS)
  set planet_radioactives := planet_value.get(RESOURCE_TYPE_RADIOACTIVES)

  // Note planets in systems with only 1 or 2 tiny/small planets
  if (lst_AI_Systems_With_Limited_Planets.indexof(planet_id) > 0) then
    set planet_isolated := TRUE
  endif

  // Convert our planet's value if finite resources game
  if Sys_Is_Finite_Resource_Game() then
    // Minerals
    if (planet_minerals <= 100000) then
      set planet_minerals := 0.0
    else
      set planet_minerals := (planet_minerals / 80000) + 25
    endif
    // Organics
    if (planet_organics <= 100000) then
      set planet_organics := 0.0
    else
      set planet_organics := (planet_organics / 80000) + 25
    endif
    // Radioactives
    if (planet_radioactives <= 100000) then
      set planet_radioactives := 0.0
    else
      set planet_radioactives := (planet_radioactives / 80000) + 25
    endif
  endif

  // Note the quality of our planet's resources
  set good_minerals := planet_minerals >= 100
  set good_organics := planet_organics >= 100
  set good_radioactives := planet_radioactives >= 100
  set good_resources := (planet_minerals + planet_organics + planet_radioactives > 250)

  // Note the number of basic facilities present
  set num_facilities := Get_Total_Number_Of_Facilities_On_Planet(planet_id)
  set num_spaceyards := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_space_yard)
  set num_factories := Get_Number_Of_Facilities_On_Planet(planet_id,lng_facility_id_comp_factory) + Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_sys_robotoid)
  set num_minerals := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_minerals)
  set num_organics := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_organics)
  set num_radioactives := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_radioactives)
  set num_monolith := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_monolith)
  set num_research := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_research_pts)
  set num_intel := Get_Number_Of_Facilities_On_Planet(planet_id, lng_facility_id_intel_pts)
  set num_industrial_facilities := num_spaceyards + num_factories + num_minerals + num_organics + num_radioactives + num_monolith

  // Is this planet industrial?
  if (num_facilities >= 10) then
    if (num_industrial_facilities >= 6) then
      set planet_is_industrial := TRUE
    endif
  endif

  // Which planetary special facilities should we consider constructing?
  set skip_spaceport := Is_Facility_Present_In_System(planet_sys, lng_facility_id_spaceport) or Is_Facility_Queued_In_System(planet_sys, "Space Port") or (bool_Race_Does_Not_Use_Spaceports)
  set skip_spaceyard := Is_Facility_Present_In_System(planet_sys, lng_facility_id_space_yard) or Is_Facility_Ability_Queued_In_System(planet_sys, "Space Yard")
  set skip_resupply := Is_Facility_Present_In_System(planet_sys, lng_facility_id_resupply_depot) or Is_Facility_Queued_In_System(planet_sys, "Resupply Depot")

  // Special conditions for building a Space Yard ahead of a Spaceport
  if (skip_spaceport) and (skip_spaceyard) then
    if (lst_AI_Our_Colony_Systems.count() = 1) then
      set skip_spaceport := TRUE
    endif
  endif

  // Set override for "skip scrap x" flags if we don't have a Spaceport, Space Yard or Resupply Depot in the system
  if (not skip_spaceport) or (not skip_spaceyard) or (not skip_resupply) then
    set override_skip := TRUE
  endif

  // Set flags for adding specialty facilities
  // Components Factory
  if Is_Facility_Available(lng_facility_id_comp_factory) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_space_yard) then
      set skip_comp_factory := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_comp_factory) or Is_Facility_Queued_On_Planet(planet_id, "Components Factory")
    endif
  endif
  // Monolith Facility
  if Is_Facility_Available(lng_facility_id_monolith) then
    set skip_monolith := (not good_resources)
  endif
  // Time Shrine
  if (num_resource > 10) then
    If Is_Facility_Available(lng_facility_id_prod_mod) then
      set skip_prod_mod := Is_Facility_Present_In_System(planet_sys, lng_facility_id_prod_mod) or Is_Facility_Queued_In_System(planet_sys, "Time Shrine")
    endif
  endif
  // Mineral Scanner
  if (num_minerals > 5) and (not skip_prod_mod) then
    if Is_Facility_Available(lng_facility_id_minerals_mod) then
      set skip_minerals_mod := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_minerals_mod) or Is_Facility_Queued_On_Planet(planet_id, "Mineral Scanner")
    endif
  endif
  // Hybrid Eco-Farms
  if (num_organics > 5) and (not skip_prod_mod) then
    if Is_Facility_Available(lng_facility_id_organics_mod) then
      set skip_organics_mod := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_organics_mod) or Is_Facility_Queued_On_Planet(planet_id, "Hybrid Eco-Farms")
    endif
  endif
  // Radioactives Collider
  if (num_radioactives > 5) and (not skip_prod_mod) then
    if Is_Facility_Available(lng_facility_id_radioactives_mod) then
      set skip_radioactives_mod := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_radioactives_mod) or Is_Facility_Queued_On_Planet(planet_id, "Radioactives Collider")
    endif
  endif
  // Central Computer Complex
  if (num_research > 5) and (not bool_Race_At_Max_Tech) then
    if Is_Facility_Available(lng_facility_id_research_pts_mod) then
      set skip_research_mod := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_research_pts_mod) or Is_Facility_Queued_On_Planet(planet_id, "Central Computer Complex")
    endif
  endif
  // Citizen Databank Complex
  if (num_intel > 5) then
    if Is_Facility_Available(lng_facility_id_intel_pts_mod) then
      set skip_intel_mod := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_intel_pts_mod) or Is_Facility_Queued_On_Planet(planet_id, "Citizen Databank Complex")
    endif
  endif
  // Atmospheric Modification Plant
  if (not planet_breathable) and (not Get_Planet_Physical_Type_Name(planet_id) = "Gas Giant") and (not Get_Native_Atmosphere(sys_long_Player_ID) = "None") then
    if Is_Facility_Available(lng_facility_id_planet_atmosphere) then
      if Is_Facility_Available(lng_facility_id_planet_atmosphere) then
        set skip_planet_atmosphere := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_planet_atmosphere) or Is_Facility_Queued_On_Planet(planet_id, "Atmospheric Modification Plant")
      endif
    endif
  endif
  // Value Improvement Plant
  if ((num_minerals + num_organics + num_radioactives + num_monolith) > 10) and ((planet_minerals < 150) and (planet_organics < 150) and (planet_radioactives < 150)) then
    if Is_Facility_Available(lng_facility_id_planet_value) then
      set skip_planet_value := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_planet_value) or Is_Facility_Queued_On_Planet(planet_id, "Value Improvement Plant") or Is_Facility_Present_In_System(planet_sys, lng_facility_id_value_mod) or Is_Facility_Queued_In_System(planet_sys, "Nature Shrine")
    endif
  endif
  // Climate Control Facility
  if (planet_num_facilities >= 15) or (planet_conditions < 0.5) or (planet_pollution_pts > 20) then
    if Is_Facility_Available(lng_facility_id_planet_conditions) then
      set skip_planet_conditions := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_planet_conditions) or Is_Facility_Queued_On_Planet(planet_id, "Climate Control Facility") or Is_Facility_Present_In_System(planet_sys, lng_facility_id_value_mod) or Is_Facility_Queued_In_System(planet_sys, "Nature Shrine")
    endif
  endif
  // Shield Generator Facility
  if (planet_num_facilities > 20) then
    if Is_Facility_Available(lng_facility_id_shield_pts) then
      set skip_shield_pts := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_shield_pts) or Is_Facility_Ability_Queued_On_Planet(planet_id, "Shield Generation")
    endif
  endif
  // Crystalline Restructuring Plant
  if (planet_num_facilities > 5) then
    If Is_Facility_Available(lng_facility_id_maint_mod) then
      set skip_shield_mod := Is_Facility_Present_In_System(planet_sys, lng_facility_id_maint_mod) or Is_Facility_Queued_In_System(planet_sys, "Crystalline Restructuring Plant")
    endif
  endif
  // Energy Transmission Lens
  if (planet_num_facilities > 5) then
    If Is_Facility_Available(lng_facility_id_shield_mod) then
      set skip_shield_mod := Is_Facility_Present_In_System(planet_sys, lng_facility_id_shield_mod) or Is_Facility_Queued_In_System(planet_sys, "Energy Transmission Lens")
    endif
  endif
  // War Shrine/Events Predictor/Subspace Transmitter
  if (planet_num_facilities > 5) then
    If Is_Facility_Available(lng_facility_id_combat_mod) then
      set skip_combat_mod := Is_Facility_Present_In_System(planet_sys, lng_facility_id_combat_mod) or Is_Facility_Queued_In_System(planet_sys, "War Shrine") or Is_Facility_Queued_In_System(planet_sys, "Events Predictor") or Is_Facility_Queued_In_System(planet_sys, "Subspace Transmitter")
    endif
  endif
  // Death Shrine
  if (planet_num_facilities > 5) then
    If Is_Facility_Available(lng_facility_id_damage_mod) then
      set skip_damage_mod := Is_Facility_Present_In_System(planet_sys, lng_facility_id_damage_mod) or Is_Facility_Queued_In_System(planet_sys, "Death Shrine")
    endif
  endif
  // Ship Training Complex
  if (planet_num_facilities > 5) then
    if Is_Facility_Available(lng_facility_id_ship_training) then
      set skip_ship_training := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_ship_training) or Is_Facility_Ability_Queued_On_Planet(planet_id, "Ship Training")
    endif
  endif
  // Fleet Training Complex
  if (planet_num_facilities > 5) then
    if Is_Facility_Available(lng_facility_id_fleet_training) then
      set skip_fleet_training := Is_Facility_Present_On_Planet(planet_id, lng_facility_id_fleet_training) or Is_Facility_Ability_Queued_On_Planet(planet_id, "Fleet Training")
    endif
  endif
  // Interdimensional Portal Facility
  if (planet_num_facilities > 5) then
    if Is_Facility_Available(lng_facility_id_extra_facility_space) then
      set skip_extra_space := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_extra_facility_space) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Interdimensional Portal Facility")
    endif
  endif
  // Dimensional Rift Projector
  if (planet_num_facilities > 5) then
    if Is_Facility_Available(lng_facility_id_dimensional_rift) then
      set skip_dimensional_rift := Is_Facility_Present_In_System(planet_sys, lng_facility_id_dimensional_rift) or Is_Facility_Queued_In_System(planet_sys, "Dimensional Rift Projector")
    endif
  endif

  // Skip scrapping needed facilities (unless it's an emergency)
  if (not override_skip) then
    // Don't scrap resource facilities if we are low in the corresponding resource
    set skip_scrap_minerals := bool_Race_Minerals_Low or bool_Race_Minerals_Prod_Low or bool_Race_Minerals_Deficit
    set skip_scrap_organics := bool_Race_Organics_Low or bool_Race_Organics_Prod_Low or bool_Race_Organics_Deficit
    set skip_scrap_radioactives := bool_Race_Radioactives_Low or bool_Race_Radioactives_Prod_Low or bool_Race_Radioactives_Deficit
    set skip_scrap_monolith := skip_scrap_minerals or skip_scrap_organics or skip_scrap_radioactives or good_resources
    // Don't scrap research or intel facilities if we need the points
    set skip_scrap_research := bool_Enemy_Far_Ahead_In_Research or bool_Race_Boost_Research
    set skip_scrap_intel := bool_Enemy_Intel_Overload or bool_Race_Boost_Intel
  endif

  // Scrap unneeded facilities that don't cost us anything
  // Scrap Space Ports if we don't need them
  if (bool_Race_Does_Not_Use_Spaceports) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_spaceport) then
      call scrap_Facility(planet_id, lng_facility_id_spaceport, FALSE)
    endif
    // For planets in asteroid systems don't worry about spaceports
    if (planet_isolated) then
      call scrap_Facility(planet_id, lng_facility_id_spaceport, FALSE)
    endif
  endif
  // Scrap Atmospheric Modification Plant if planet is breathable
  if (planet_breathable) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_planet_atmosphere) then
      call scrap_Facility(planet_id, lng_facility_id_planet_atmosphere, FALSE)
    endif
  endif
  // Scrap Climate Control Facility if conditions are optimal
  if (planet_conditions >= 1.5) and (not planet_is_industrial) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_planet_conditions) then
      call Scrap_Facility(planet_id, lng_facility_id_planet_conditions, FALSE)
    endif
  endif
  // Scrap Value Improvement Plant if resource value at maximum
  if (not Sys_Is_Finite_Resource_Game()) and (planet_minerals >= 150) and (planet_organics >= 150) and (planet_radioactives >= 150) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_planet_value) then
      call Scrap_Facility(planet_id, lng_facility_id_planet_value, FALSE)
    endif
  endif
  // Research
  if (bool_Race_At_Max_Tech) or (planet_isolated) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_research_pts) then
      call Scrap_Facility(planet_id, lng_facility_id_research_pts, FALSE)
    endif
  endif
  // Central Computer Complex
  if (bool_Race_At_Max_Tech) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_research_pts_mod) then
      call Scrap_Facility(planet_id, lng_facility_id_research_pts_mod, FALSE)
    endif
  endif
  // System Central Computer Complex
  if (bool_Race_At_Max_Tech) then
    if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_research_pts_mod) then
      call Scrap_Facility(planet_id, lng_facility_id_research_pts_sys_mod, FALSE)
    endif
  endif
  // Temporary Fixes (may no longer be needed; review in v130)
  // Scrap Ultra-Recycler if we have more than 1 in the system
  if (Get_Number_Of_Facilities_In_System(planet_sys, lng_facility_id_resource_reclamation) > 1) then
    call Scrap_Facility(planet_id, lng_facility_id_resource_reclamation, FALSE)
  endif
  // Scrap Psychic Scanner if we have more than 1 in the system
  if (Get_Number_Of_Facilities_In_System(planet_sys, lng_facility_id_scanner) > 1) then
    call Scrap_Facility(planet_id, lng_facility_id_scanner, FALSE)
  endif
  // Scrap Component Factories on planets with no Space Yard
  if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_comp_factory) then
    if (not Is_Facility_Present_On_Planet(planet_id, lng_facility_id_Space_Yard)) then
      call Scrap_Facility(planet_id, lng_facility_id_comp_factory, FALSE)
    endif
  endif

  // Get our planet's space remaining
  set planet_space_left := Sys_Get_Space_Object_Facility_Space_Remaining(planet_id)

  // If there's no space left for facilities, considering scrapping a facility and replacing it with another desired facility
  if (planet_space_left < 1000) then
    if (not gbl_max_facilities_scrapped) then
      // Research facility?
      if (num_research > 0) and (not skip_scrap_research) then
        if (bool_Race_At_Max_Tech) then
          set facility_to_scrap := lng_facility_id_research_pts
        endif
      endif
      // Intelligence facility?
      if ((num_intel > 0) and (not skip_scrap_intel)) or (planet_isolated) then
        if (bool_Race_At_Max_Intel) and (planet_colony_type <> AI_STR_COLONY_TYPE_INTEL) then
          set facility_to_scrap := lng_facility_id_intel_pts
        endif
      endif
      // Minerals facility?
      if ((num_minerals > 0) and (not skip_scrap_minerals)) or (planet_isolated) then
        if (bool_Race_Minerals_Prod_High) then
          set facility_to_scrap := lng_facility_id_minerals
        endif
      endif
      // Organics facility?
      if ((num_organics > 0) and (not skip_scrap_organics)) or (planet_isolated) then
        if (bool_Race_Organics_Prod_High) then
          set facility_to_scrap := lng_facility_id_organics
        endif
      endif
      // Radioactives facility?
      if ((num_radioactives > 0) and (not skip_scrap_radioactives)) or (planet_isolated) then
        if (bool_Race_Radioactives_Prod_High) then
          set facility_to_scrap := lng_facility_id_radioactives
        endif
      endif
      // Monolith facility?
      if ((num_monolith > 0) and (not skip_scrap_monolith)) or (planet_isolated) then
        set facility_to_scrap := lng_facility_id_monolith
      endif
      // Resupply Depot?
      if (num_facilities < 10) and (facility_to_scrap = 0) then
        if Is_Facility_Present_On_Planet(planet_id, lng_facility_id_resupply_depot) then
          if (Get_Number_Of_Facilities_In_System(planet_id, lng_facility_id_resupply_depot) > 1) or (not skip_spaceport) or (not skip_spaceyard) then
            set facility_to_scrap := lng_facility_id_resupply_depot
          endif
        endif
      endif

      // Debug output (remove once debugged)
      if (facility_to_scrap > 0) then
        call Sys_Debug_Print("Planets", "    - Considering scrapping " + Sys_Get_Facility_Name(facility_to_scrap))
      endif

      // Increase resource production without regard to colony type
      if (facility_to_scrap > 0) then
        // Add a Space Port
        if (not skip_spaceport) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_spaceport)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Space Port to replace scrapped facility")
          endif
        endif
        // Add a Space Yard
        if ((not skip_spaceyard) and (not gbl_facility_scrapped)) or (planet_isolated and skip_resupply) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_space_yard)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Space Yard to replace scrapped facility")
          endif
        endif
        // Add a Resupply Depot
        if ((not skip_resupply) and (not gbl_facility_scrapped)) or (planet_isolated and not skip_resupply) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_resupply_depot)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Resupply Depot to replace scrapped facility")
          endif
        endif
        // Resource facilities
        // Add a Monolith Facility for planets with good overall resource value
        if (not skip_monolith) and (not gbl_facility_scrapped) then
          if (facility_to_scrap <> lng_facility_id_monolith) then
            if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
              call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_monolith)
              // Debug output
              call Sys_Debug_Print("Planets", "      - Added Monolith facility to replace scrapped facility")
            endif
          endif
        endif
        // Add a Mineral Facility if we are low on minerals
        if (bool_Race_Minerals_Low or bool_Race_Minerals_Prod_Low) and (planet_minerals >= 80) and (facility_to_scrap <> lng_facility_id_minerals) and (facility_to_scrap <> lng_facility_id_monolith) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_minerals)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Minerals Mine to replace scrapped facility")
          endif
        endif
        // Add an Organics Facility if we are low on organics
        if (bool_Race_Organics_Low or bool_Race_Organics_Prod_Low) and (planet_organics >= 80) and (facility_to_scrap <> lng_facility_id_organics) and (facility_to_scrap <> lng_facility_id_monolith) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id,lng_facility_id_organics)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Organics Farm to replace scrapped facility")
          endif
        endif
        // Add a Radioactives Facility if we are low on radioactives
        if (bool_Race_Radioactives_Low or bool_Race_Radioactives_Prod_Low) and (planet_radioactives >= 80) and (facility_to_scrap <> lng_facility_id_radioactives) and (facility_to_scrap <> lng_facility_id_monolith) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_radioactives)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Radioactives Extractor to replace scrapped facility")
          endif
        endif
        // Planet improvement facilities
        // Components Factory
        if (not skip_comp_factory) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_comp_factory)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Components Factory to replace scrapped facility")
          endif
        endif
        // Value Improvement Plant
        if (not skip_planet_value) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_planet_value)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Value Improvement Plant to replace scrapped facility")
          endif
        endif
        // Climate Control Facility
        if (not skip_planet_conditions) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_planet_value)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Climate Control Facility to replace scrapped facility")
          endif
        endif
        // Atmospheric Modification Plant
        if (not skip_planet_atmosphere) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_planet_atmosphere)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Atmospheric Modification Plant to replace scrapped facility")
          endif
        endif
        // Death Shrine
        if (not skip_damage_mod) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_damage_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Death Shrine to replace scrapped facility")
          endif
        endif
        // War Shrine/Events Predictor/Subspace Transmitter
        if (not skip_combat_mod) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_combat_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Combat Modifier Facility to replace scrapped facility")
          endif
        endif
        // Fleet Training Complex
        if (not skip_fleet_training) and (planet_colony_type = AI_STR_COLONY_TYPE_MILITARY) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_fleet_training)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Fleet Training Complex to replace scrapped facility")
          endif
        endif
        // Ship Training Complex
        if (not skip_ship_training) and (planet_colony_type = AI_STR_COLONY_TYPE_MILITARY) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_ship_training)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Ship Training Complex to replace scrapped facility")
          endif
        endif
        // Interdimensional Portal Facility
        if (not skip_extra_space) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_extra_facility_space)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Interdimensional Portal Facility to replace scrapped facility")
          endif
        endif
        // Dimensional Rift Projector
        if (not skip_dimensional_rift) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_dimensional_rift)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Dimension Rift Projector to replace scrapped facility")
          endif
        endif
        // Shield Generator
        if (not skip_shield_pts) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_shield_pts)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Planetary Shield Generator to replace scrapped facility")
          endif
        endif
        // Energy Transmission Lens
        if (not skip_shield_mod) and (not gbl_facility_scrapped) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_shield_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Energy Transmission Lens to replace scrapped facility")
          endif
        endif
      endif

      // Improve minerals production or storage
      if (planet_colony_type = AI_STR_COLONY_TYPE_MINING) or (planet_colony_type = AI_STR_COLONY_TYPE_MINING_FARMING) or (planet_colony_type = AI_STR_COLONY_TYPE_MINING_REFINING) or (planet_colony_type = AI_STR_COLONY_TYPE_RESOURCE) then
        // Add a Minerals Scanner to increase minerals production
        if (not skip_minerals_mod) then
          if Scrap_Facility(planet_id, lng_facility_id_minerals, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_minerals_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Mineral Scanner to replace scrapped facility")
          endif
        endif
        // Add a Minerals Resource Storage if we need minerals storage
        if (bool_Race_Needs_Minerals_Storage) and (lng_Minerals_Surplus > 50000) then
          if Scrap_Facility(planet_id, lng_facility_id_minerals, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_minerals_storage)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Minerals Resource Storage to replace scrapped facility")
          endif
         endif
      endif

      // Improve organics production or storage
      if (planet_colony_type = AI_STR_COLONY_TYPE_FARMING) or (planet_colony_type = AI_STR_COLONY_TYPE_MINING_FARMING) or (planet_colony_type = AI_STR_COLONY_TYPE_FARMING_REFINING) or (planet_colony_type = AI_STR_COLONY_TYPE_RESOURCE) then
        // Add a Hybrid Eco-Farm to increase organics production
        if (not skip_organics_mod) then
          if Scrap_Facility(planet_id, lng_facility_id_organics, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_organics_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Hybrid Eco-Farm to replace scrapped facility")
          endif
        endif
        // Add an Organics Resource Storage if we need organics storage
        if (bool_Race_Needs_Organics_Storage) and (lng_Organics_Surplus > 50000) then
          if Scrap_Facility(planet_id, lng_facility_id_organics, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_organics_storage)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Organic Resource Storage to replace scrapped facility")
          endif
        endif
      endif

      // Improve radioactives production or storage
      if (planet_colony_type = AI_STR_COLONY_TYPE_REFINING) or (planet_colony_type = AI_STR_COLONY_TYPE_MINING_REFINING) or (planet_colony_type = AI_STR_COLONY_TYPE_FARMING_REFINING) or (planet_colony_type = AI_STR_COLONY_TYPE_RESOURCE) then
        // Add a Radioactives Collider to increase radioactives production
        if (not skip_radioactives_mod) then
          if Scrap_Facility(planet_id, lng_facility_id_radioactives, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_radioactives_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Radioactives Collider to replace scrapped facility")
          endif
        endif
        // Add an Radioactives Resource Storage if we need radioactives storage
        if (bool_Race_Needs_Radioactives_Storage) and (lng_Radioactives_Surplus > 50000) then
          if Scrap_Facility(planet_id, lng_facility_id_radioactives, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_radioactives_storage)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Radioactive Resource Storage to replace scrapped facility")
          endif
        endif
      endif

      // Improve all resource production (Time Shrine)
      if (not gbl_facility_scrapped) then
        if (not skip_prod_mod) then
          if Scrap_Facility(planet_id, facility_to_scrap, FALSE) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_prod_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Time Shrine to replace scrapped facility")
          endif
        endif
      endif

      // Scrap the facility but let the construction script determine the new addition
      if (facility_to_scrap > 0) and (not gbl_facility_scrapped) then
        set facility_to_scrap := 0
      endif

      // See if we can improve our research or intel production
      if (not gbl_facility_scrapped) then
        // Improve research points production
        if (planet_colony_type = AI_STR_COLONY_TYPE_RESEARCH) or (planet_colony_type = AI_STR_COLONY_TYPE_RESEARCH_INTEL) or (planet_colony_type = AI_STR_COLONY_TYPE_MILITARY) or (planet_colony_type = AI_STR_COLONY_TYPE_CONSTRUCTION) or (planet_colony_type = AI_STR_COLONY_TYPE_RESUPPLY) then
          // Consider replacing another facility with a Research Center if we are behind in research...
          if (bool_Enemy_Ahead_In_Research) and (Sys_Get_Random_Long(1, 100) > lng_Pct_Pts_Research) then
            if (num_intel > 0) and (not skip_scrap_intel) and (lng_Current_Pct_Intel > lng_Pct_Pts_Intel) then
              set facility_to_scrap := lng_facility_id_intel_pts
            else
              if (num_organics > 0) and (bool_Race_Organics_High or bool_Race_Organics_Prod_High) then
                set facility_to_scrap := lng_facility_id_organics
              else
                if (num_radioactives > 0) and (bool_Race_Radioactives_High or bool_Race_Radioactives_Prod_High) then
                  set facility_to_scrap := lng_facility_id_radioactives
                else
                  if (num_minerals > 0) and (bool_Race_Minerals_High or bool_Race_Minerals_Prod_High) then
                    set facility_to_scrap := lng_facility_id_minerals
                  else
                    if (num_monolith > 0) and (bool_Race_Minerals_High and bool_Race_Organics_High and bool_Race_Radioactives_High) then
                       set facility_to_scrap := lng_facility_id_monolith
                    endif
                  endif
                endif
              endif
            endif
          endif
        endif
         // Add a Research Center to increase research points production
        if (facility_to_scrap > 0) then
          if Scrap_Facility(planet_id, facility_to_scrap, TRUE) and (not bool_Race_At_Max_Tech) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_research_pts)
            // Debug output
             call Sys_Debug_Print("Planets", "      - Added Research Center to replace scrapped facility")
          endif
        endif
        // Add a Central Computer Complex to increase research points production
        if (not skip_research_mod) then
          if Scrap_Facility(planet_id, lng_facility_id_research_pts, TRUE) and (not bool_Race_At_Max_Tech) then
            call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_research_pts_mod)
            // Debug output
            call Sys_Debug_Print("Planets", "      - Added Central Computer Complex to replace scrapped facility")
          endif
        endif
 
        // Improve intel points production
        if (bool_Intel_Is_Allowed) then
          if (planet_colony_type = AI_STR_COLONY_TYPE_INTEL) or (planet_colony_type = AI_STR_COLONY_TYPE_RESEARCH_INTEL) or (planet_colony_type = AI_STR_COLONY_TYPE_MILITARY) or (planet_colony_type = AI_STR_COLONY_TYPE_CONSTRUCTION) or (planet_colony_type = AI_STR_COLONY_TYPE_RESUPPLY) then
            set facility_to_scrap := 0
            // Consider replacing a resource facility with intel if we are behind in intel
            if (bool_Enemy_Ahead_In_Intel) or (Sys_Get_Random_Long(1, 2) = 1) then
              if (num_organics > 0) and ((bool_Race_Organics_High) or (bool_Race_Organics_Prod_High)) then
                set facility_to_scrap := lng_facility_id_organics
              else
                if (num_radioactives > 0) and ((bool_Race_Radioactives_High) or (bool_Race_Radioactives_Prod_High)) then
                  set facility_to_scrap := lng_facility_id_radioactives
                else
                  if (num_minerals > 0) and ((bool_Race_Minerals_High) or (bool_Race_Minerals_Prod_High)) then
                    set facility_to_scrap := lng_facility_id_minerals
                  else
                    if (num_monolith > 0) and (bool_Race_Minerals_High and bool_Race_Organics_High and bool_Race_Radioactives_High) then
                      set facility_to_scrap := lng_facility_id_monolith
                    else
                      if (num_research > 0) and ((not bool_Enemy_Far_Ahead_In_Research) and (lng_Current_Pct_Research > lng_Pct_Pts_Research) or (bool_Race_At_Max_Tech)) then
                        set facility_to_scrap := lng_facility_id_research_pts
                      endif
                    endif
                  endif
                endif
              endif
            endif
            // Add an Intelligence Center to increase intel points production
            if (facility_to_scrap > 0) then
              if Scrap_Facility(planet_id, facility_to_scrap, TRUE) then
                call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_intel_pts)
                // Debug output
                call Sys_Debug_Print("Planets", "      - Added Intelligence Center to replace scrapped facility")
              endif
            endif
            // Add a Citizen Databank Complex to increase intel points production
            if (not skip_intel_mod) then
              if Scrap_Facility(planet_id, lng_facility_id_intel_pts, TRUE) then
                call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_intel_pts_mod)
                // Debug output
                call Sys_Debug_Print("Planets", "      - Added Citizen Databank Complex to replace scrapped facility")
              endif
            endif
            // Add an Intelligence Center in place of a Research Center if we are overwhelmed by intelligence actions
            if (bool_Enemy_Intel_Overload) then
              if (num_research > 0) then
                if Scrap_Facility(planet_id, lng_facility_id_research_pts, TRUE) then
                  call Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, planet_id, lng_facility_id_intel_pts)
                  // Debug output
                  call Sys_Debug_Print("Planets", "      - Added Intelligence Center to replace scrapped facility")
                endif
              endif
            endif
          endif
        endif
      endif
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Scrap_Facility
//------------------------------------------------------------------------
function Scrap_Facility returns boolean
params
  planet_id:                 long
  facil_id:                  long
  add_non_resource_facility: boolean
vars
  cargo_index:               long := 0
  cargo_item_count:          long
  cargo_item_id:             long
  facility_scrapped:         boolean := FALSE
  facility_name:             string
begin

  // Get our facility's details
  set facility_name := Sys_Get_Facility_Name(facil_id)

  // Set our maximum number of facilities to scrap in one turn
  if (bool_Race_Minerals_High) and (bool_Race_Organics_High) and (bool_Race_Radioactives_High) then
    set lng_Max_Facilities_To_Scrap := Sys_Trunc(lng_AI_Empire_Num_Facilities ^ 0.5)
  else
    set lng_Max_Facilities_To_Scrap := Sys_Trunc(lng_AI_Empire_Num_Facilities ^ 0.4)
  endif

  // Set our maximum number of non-resource facilities to add in one turn
  if (bool_Race_Minerals_Low) or (bool_Race_Organics_Low) or (bool_Race_Radioactives_Low) then
    set lng_Max_Facilities_To_Add := Sys_Divide_Long(lng_Minerals_Surplus, 5000)
    set lng_Max_Facilities_To_Add := Sys_Min_Long(lng_Max_Facilities_To_Add, Sys_Divide_Long(lng_Organics_Surplus, 5000))
    set lng_Max_Facilities_To_Add := Sys_Min_Long(lng_Max_Facilities_To_Add, Sys_Divide_Long(lng_Radioactives_Surplus, 5000))
  else
    set lng_Max_Facilities_To_Add := Sys_Trunc(lng_AI_Empire_Num_Facilities * 0.02)
  endif

  // Limit addition of non-resource additions
  if (add_non_resource_facility) then
    set lng_Scrap_Facility_Added_Count := lng_Scrap_Facility_Added_Count + 1
    // Debug output
    call Sys_Debug_Print("Planets", "        - Adding non-resource facility")
  endif

  if (add_non_resource_facility) and (lng_Scrap_Facility_Added_Count > lng_Max_Facilities_To_Add) then
    set gbl_facility_scrapped := TRUE
    // Debug output
    call Sys_Debug_Print("Planets", "        - Scrap will fail")
  endif

  if (not gbl_facility_scrapped) then
    // Count the items in our planet's cargo
    set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)

    // Check for the facility on the planet
    if (cargo_item_count > 0) then
      loop
        set cargo_index := cargo_index + 1
        set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
          if (Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id) = CARGO_ITEM_TYPE_FACILITY) then
            if (Sys_Get_Space_Object_Cargo_Item_Facility_ID(planet_id, cargo_item_id) = facil_id) then
              set facility_scrapped := Sys_Space_Object_Scrap_Cargo(planet_id, cargo_item_id)
              set lng_Scrap_Facility_Count := lng_Scrap_Facility_Count + 1
              // Debug output
              call Sys_Debug_Print("Planets", "    - Scrapped " + facility_name)
            endif
          endif
        exitwhen (cargo_index >= cargo_item_count) or (facility_scrapped)
      endloop
    endif
  endif

  // Only scrap 1 facility per planet per turn
  if (facility_scrapped) then
    set gbl_facility_scrapped := TRUE
    // Note when we have scrapped our maximum number of facilities for the turn
    if (lng_Scrap_Facility_Count >= lng_Max_Facilities_To_Scrap) then
      set gbl_max_facilities_scrapped := TRUE
    endif
    // Update our resource modifiers
    call Compute_Resource_Balances()
    call Compute_Resource_Levels()
    // call Estimate_Pending_Resource_Production()
  endif

  return facility_scrapped
end

//------------------------------------------------------------------------
// Scrap_Population
//------------------------------------------------------------------------
function Scrap_Population returns boolean
params
  planet_id:                 long
vars
  planet_atmosphere:         string
  population_atmosphere:     string
  population_amount:         long
  cargo_index:               long := 0
  cargo_item_count:          long
  cargo_item_id:             long
  has_breathers:             boolean := FALSE
  has_non_breathers:         boolean := FALSE
  scrap_count:               long
begin

  // Get our planet's details
  If Sys_Is_Planet_Domed(planet_id) then
    // Debug output
    call Sys_Debug_Print("Planets", "    - Domed")
  else
    // Debug output
    call Sys_Debug_Print("Planets", "    - Not Domed")
  endif
  // What atmosphere?
  set planet_atmosphere := Get_Planet_Atmosphere_Type_Name(Sys_Get_Planet_Atmosphere_Type(planet_id))
  // Debug Output
  call Sys_Debug_Print("Planets", "    - Atmosphere = " + planet_atmosphere)

  // Get the items in our planet's cargo
  set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)

  // Check the planet's population groups to see if they breath the atmosphere
  if (cargo_item_count > 0) then
    loop
      set cargo_index := cargo_index + 1
      set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
      // Check the planet's population for breathers and non-breathers
      if (Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id) = CARGO_ITEM_TYPE_POPULATION) then
        set population_atmosphere := Sys_Get_Space_Object_Cargo_Item_Population_Atmosphere_Breathed(planet_id, cargo_item_id)
        set population_amount := Sys_Get_Space_Object_Cargo_Item_Space_Used(planet_id, cargo_item_id)
        set population_amount := Sys_Divide_Long(population_amount, 50)
        // Does the population breath the atmosphere?
        if (population_atmosphere = planet_atmosphere) then
          set has_breathers := TRUE
          // Debug output
          call Sys_Debug_Print("Planets", "      - " + Sys_Convert_Long_To_String(population_amount) + "M Breathing Population (" + population_atmosphere + ")" + " (Item id = " + Sys_Convert_Long_To_String(cargo_item_id) +")")
        else
          set has_non_breathers := TRUE
          // Debug output
          call Sys_Debug_Print("Planets", "      - " + Sys_Convert_Long_To_String(population_amount) + "M Non-Breathing Population (" + population_atmosphere + ")" + " (Item id = " + Sys_Convert_Long_To_String(cargo_item_id) +")")
        endif
      endif
      exitwhen (cargo_index >= cargo_item_count)
    endloop
  endif

  // If we have breathers and non-breathers then scrap(!) the non-breathing population
  if (has_breathers and has_non_breathers) then
    set cargo_index := 0  
    // Check for non-breathing population
    loop
      set cargo_index := cargo_index + 1
      set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
      // Does the population breathe the atmosphere?
      if (Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id) = CARGO_ITEM_TYPE_POPULATION) then
        set population_atmosphere := Sys_Get_Space_Object_Cargo_Item_Population_Atmosphere_Breathed(planet_id, cargo_item_id)
        // Scrap populations that don't breathe the atmosphere
        if (population_atmosphere <> planet_atmosphere) then
          if Sys_Space_Object_Scrap_Cargo(planet_id, cargo_item_id) then
            set cargo_index := cargo_index - 1
            set scrap_count := scrap_count + 1
            // Debug output
            call Sys_Debug_Print("Planets", "        - Scraped non-breathing population to undome the colony" + " (Item id = " + Sys_Convert_Long_To_String(cargo_item_id) +")")
          endif
        endif
      endif
      exitwhen (cargo_index >= (cargo_item_count - scrap_count))
    endloop
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Launch_Planetary_Fighters
//------------------------------------------------------------------------
function Launch_Planetary_Fighters returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
vars
  cargo_item_count:          long
  cargo_index:               long
  cargo_item_id:             long
  cargo_item_type:           long
  cargo_item_unit_type:      string
  sys_loc:                   long
  sect_loc:                  long
  num_in_space:              long
  num_on_planet:             long
  num_to_launch:             long
  unit_group_list:           longlist
  unit_group_count:          long
  unit_group_index:          long := 0
  unit_group_id:             long
begin

  // Get our planet's details
  set sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
  set sect_loc := Sys_Get_Space_Object_Sector_Location(planet_id)

  // Consider launching fighters if our planet is in a defense system
  if (lst_AI_Defense_Location_System.indexof(sys_loc) > 0) and (not bool_Race_At_Max_Units) then
    if (lst_AI_Defense_System_Total_Count.get(sys_loc) > 5) then
      // Check our planet's cargo for fighters
      set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)
      if (cargo_item_count > 0) then
        set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Fighter", sys_loc, sect_loc)
        set num_on_planet := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Fighter")

        if (num_on_planet > lng_AI_Min_Fighter_Group_Size) then
          set num_to_launch := Sys_Min_Long(lng_AI_Min_Fighter_Group_Size, 1000 - num_in_space)
        endif

        // Launch our planet's fighters
        if (num_to_launch > 0) then
          set cargo_index := 0
          // Debug output
          call Sys_Debug_Print("Planets", "    - Launching Fighters (" + Sys_Convert_Long_To_String(num_to_launch) + ")")
          loop
            set cargo_index := cargo_index + 1
            set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
            set cargo_item_type := Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id)
            set cargo_item_unit_type := Sys_Get_Space_Object_Cargo_Item_Unit_Type(planet_id, cargo_item_id)
            // Launch cargo items that are fighters
            if (cargo_item_type = CARGO_ITEM_TYPE_UNIT) and (cargo_item_unit_type = "Fighter") then
              call Sys_Give_Space_Object_Order_Launch_Specific_Unit(planet_id, cargo_item_id)
              set num_to_launch := num_to_launch - 1
            endif
            exitwhen (num_to_launch <= 0) or (cargo_index >= cargo_item_count)
          endloop
        endif
      endif
    endif
  endif

  // Recover our fighters if there's less than the desired amount or our planet is not in a defense system
  set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Fighter", sys_loc, sect_loc)

  if (num_in_space < lng_AI_Min_Fighter_Group_Size) or (lst_AI_Defense_Location_System.indexof(sys_loc) <= 0) then
    call Sys_Get_List_Of_Visible_Space_Objects_In_Sector(sys_long_Player_ID, SPACE_OBJECT_TYPE_UNITGROUP, sys_loc, sect_loc, unit_group_list)

    set unit_group_count := unit_group_list.count()
    if (unit_group_count > 0) then
      loop
        set unit_group_index := unit_group_index + 1
        set unit_group_id := unit_group_list.get(unit_group_index)
        if (Get_Unit_Group_Type(unit_group_id) = "Fighter") then
          call Sys_Give_Space_Object_Order_Load_All_Cargo(planet_id, cargo_item_type, "Fighter", unit_group_id)
          // Debug output
          call Sys_Debug_Print("Planets", "    - Recovered Fighters")
        endif
        exitwhen (unit_group_index >= unit_group_count)
      endloop
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Launch_Planetary_Satellites
//------------------------------------------------------------------------
function Launch_Planetary_Satellites returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
vars
  cargo_item_count:          long
  cargo_index:               long
  cargo_item_id:             long
  cargo_item_type:           long
  cargo_item_unit_type:      string
  sys_loc:                   long
  sect_loc:                  long
  num_in_space:              long
  num_on_planet:             long
  num_to_launch:             long
  unit_group_list:           longlist
  unit_group_count:          long
  unit_group_index:          long := 0
  unit_group_id:             long
begin

  // Check our planet's cargo for Satellites
  set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)
  if (cargo_item_count > 0) and (not bool_Race_At_Max_Units) then
    set sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
    set sect_loc := Sys_Get_Space_Object_Sector_Location(planet_id)
    set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Satellite", sys_loc, sect_loc)

    // Launch satellites
    set num_on_planet := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Satellite")
    if (num_on_planet > lng_AI_Min_Satellite_Group_Size * 1.5) and (not bool_Race_At_Max_Units) then
      set num_to_launch := lng_AI_Min_Satellite_Group_Size
      // Don't exceed more than 100 in the sector
      set num_to_launch := Sys_Min_Long(lng_AI_Min_Satellite_Group_Size, 100 - num_in_space)
    endif

    // Launch our planet's satellites
    if (num_to_launch > 0) then
      set cargo_index := 0
      // Debug output
      call Sys_Debug_Print("Planets", "    - Launching Satellites (" + Sys_Convert_Long_To_String(num_to_launch) + ")")
      loop
        set cargo_index := cargo_index + 1
        set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
        set cargo_item_type := Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id)
        set cargo_item_unit_type := Sys_Get_Space_Object_Cargo_Item_Unit_Type(planet_id, cargo_item_id)
        // Launch cargo items that are satellites
        if (cargo_item_type = CARGO_ITEM_TYPE_UNIT) and (cargo_item_unit_type = "Satellite") then
          call Sys_Give_Space_Object_Order_Launch_Specific_Unit(planet_id, cargo_item_id)
          set num_to_launch := num_to_launch - 1
        endif
        exitwhen (num_to_launch <= 0) or (cargo_index >= cargo_item_count)
      endloop
    endif
  endif

  // Recover our satellites if the group is too small or occasionally call them back to remove obsolete units
  set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Satellite", sys_loc, sect_loc)

  if (num_in_space < lng_AI_Min_Satellite_Group_Size) or ((Sys_Get_Random_Long(1, 2) = 1) and (not enemy_present)) then
    call Sys_Get_List_Of_Visible_Space_Objects_In_Sector(sys_long_Player_ID, SPACE_OBJECT_TYPE_UNITGROUP, sys_loc, sect_loc, unit_group_list)
    // Recover our planet's satellites
    set unit_group_count := unit_group_list.count()
    if (unit_group_count > 0) then
      loop
        set unit_group_index := unit_group_index + 1
        set unit_group_id := unit_group_list.get(unit_group_index)
        if (Get_Unit_Group_Type(unit_group_id) = "Satellite") then
          call Sys_Give_Space_Object_Order_Load_All_Cargo(planet_id, cargo_item_type, "Satellite", unit_group_id)
          // Debug output
          call Sys_Debug_Print("Planets", "    - Recovered Satellites")
        endif
        exitwhen (unit_group_index >= unit_group_count)
      endloop
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Launch_Planetary_Mines
//------------------------------------------------------------------------
function Launch_Planetary_Mines returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
vars
  cargo_item_count:          long
  cargo_index:               long
  cargo_item_id:             long
  cargo_item_type:           long
  cargo_item_unit_type:      string
  sys_loc:                   long
  sect_loc:                  long
  num_in_space:              long
  num_on_planet:             long
  num_to_launch:             long
  max_mines:                 long
  planet_size:               long
  planet_breathable:         boolean := FALSE
  unit_group_list:           longlist
  unit_group_count:          long
  unit_group_index:          long := 0
  unit_group_id:             long
begin

  // Get our planet's details
  set planet_size := Get_Planet_Size(planet_id)
  set planet_breathable := (not Sys_Is_Planet_Domed(planet_id))

  // Check our planet's cargo for Mines
  set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)

  if (cargo_item_count > 0) and (not bool_Race_At_Max_Units) then
    set sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
    set sect_loc := Sys_Get_Space_Object_Sector_Location(planet_id)
    set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Mine", sys_loc, sect_loc)

    // Get the number of mines in cargo
    set num_on_planet := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Mine")

    // Determine the maximum number of mines to launch
    if (planet_breathable) then
      set max_mines := planet_size * lng_AI_Min_Mine_Group_Size
    else
      set max_mines := planet_size * Sys_Divide_Long(lng_AI_Min_Mine_Group_Size, 2)
    endif

    // Launch mines more frequently for planets in our defense system locations
    if (lst_AI_Defense_Location_System.indexof(sys_loc) > 0) then
      if (lst_AI_Defense_System_Total_Count.get(sys_loc) > 5) then
        set num_to_launch := num_on_planet
      else
        if (num_on_planet > lng_AI_Min_Mine_Group_Size) and (num_in_space < lng_AI_Min_Mine_Group_Size) then
          set num_to_launch := Sys_Min_Long(lng_AI_Min_Mine_Group_Size, 1000 - num_in_space)
        endif
      endif
    else
      if (num_on_planet > lng_AI_Min_Mine_Group_Size * 2) and (num_in_space < max_mines - (Sys_Divide_Long(lng_AI_Min_Mine_Group_Size, 2))) then
        set num_to_launch := Sys_Min_Long(Sys_Divide_Long(lng_AI_Min_Mine_Group_Size, 2), 1000 - num_in_space)
      endif
    endif

    // Launch our planet's mines
    if (num_to_launch > 0) then
      set cargo_index := 0
      // Debug output
      call Sys_Debug_Print("Planets", "    - Launching Mines (" + Sys_Convert_Long_To_String(num_to_launch) + ")")
      loop
        set cargo_index := cargo_index + 1
        set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
        set cargo_item_type := Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id)
        set cargo_item_unit_type := Sys_Get_Space_Object_Cargo_Item_Unit_Type(planet_id, cargo_item_id)
        // Launch cargo items that are mines
        if (cargo_item_type = CARGO_ITEM_TYPE_UNIT) and (cargo_item_unit_type = "Mine") then
          call Sys_Give_Space_Object_Order_Launch_Specific_Unit(planet_id, cargo_item_id)
          set num_to_launch := num_to_launch - 1
        endif
        exitwhen (num_to_launch <= 0) or (cargo_index >= cargo_item_count)
      endloop
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Launch_Planetary_Drones
//------------------------------------------------------------------------
function Launch_Planetary_Drones returns boolean
params
  planet_id:                 long
  enemy_present:             boolean
vars
  cargo_item_count:          long
  cargo_index:               long
  cargo_item_id:             long
  cargo_item_type:           long
  cargo_item_unit_type:      string
  cargo_item_design_id:      long
  cargo_item_design_type:    string
  sys_loc:                   long
  sect_loc:                  long
  num_in_space:              long
  num_on_planet:             long
  num_to_launch:             long
  unit_group_list:           longlist
  unit_group_count:          long
  unit_group_index:          long := 0
  unit_group_id:             long

begin

  // Get our planet's details
  set sys_loc := Sys_Get_Space_Object_System_Location(planet_id)
  set sect_loc := Sys_Get_Space_Object_Sector_Location(planet_id)

  // Consider launching drones if our planet is in a defense system
  if (lst_AI_Defense_Location_System.indexof(sys_loc) > 0) and (not bool_Race_At_Max_Units) then
    // Check our planet's cargo for drones
    set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)
    if (cargo_item_count > 0) then
      set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Drone", sys_loc, sect_loc)
      set num_on_planet := Sys_Get_Space_Object_Cargo_Item_Type_Count(planet_id, CARGO_ITEM_TYPE_UNIT, "Drone")

      if (num_on_planet > lng_AI_Min_Drone_Group_Size) then
        set num_to_launch := Sys_Min_Long(lng_AI_Min_Drone_Group_Size, 100 - num_in_space)
      endif

      // Launch our planet's drones
      if (num_to_launch > 0) then
        set cargo_index := 0
        // Debug output
        call Sys_Debug_Print("Planets", "    - Launching Drones (" + Sys_Convert_Long_To_String(num_to_launch) + ")")
        loop
          set cargo_index := cargo_index + 1
          set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
          set cargo_item_type := Sys_Get_Space_Object_Cargo_Item_Type(planet_id, cargo_item_id)
          set cargo_item_unit_type := Sys_Get_Space_Object_Cargo_Item_Unit_Type(planet_id, cargo_item_id)
          set cargo_item_design_id := Sys_Get_Space_Object_Cargo_Item_Design_ID(planet_id, cargo_item_id)
          set cargo_item_design_type := Sys_Get_Vehicle_Design_Name(cargo_item_design_id)
          // Launch the Drones
          if (cargo_item_type = CARGO_ITEM_TYPE_UNIT) and (cargo_item_unit_type = "Drone") then
            call Sys_Give_Space_Object_Order_Launch_Specific_Unit(planet_id, cargo_item_id)
            set num_to_launch := num_to_launch - 1
          endif
          exitwhen (num_to_launch <= 0) or (cargo_index >= cargo_item_count)
        endloop
      endif
    endif
  endif

  // Recover Drones if there's less than the desired amount or our planet is not in a defense system
  set num_in_space := Sys_Get_Number_Of_Units_In_Space_Sector(sys_long_Player_ID, "Drone", sys_loc, sect_loc)

  if (num_in_space < lng_AI_Min_Drone_Group_Size) or (lst_AI_Defense_Location_System.indexof(sys_loc) <= 0) then
    call Sys_Get_List_Of_Visible_Space_Objects_In_Sector(sys_long_Player_ID, SPACE_OBJECT_TYPE_UNITGROUP, sys_loc, sect_loc, unit_group_list)

    set unit_group_count := unit_group_list.count()
    if (unit_group_count > 0) then
      loop
        set unit_group_index := unit_group_index + 1
        set unit_group_id := unit_group_list.get(unit_group_index)
        if (Get_Unit_Group_Type(unit_group_id) = "Drone") then
          call Sys_Give_Space_Object_Order_Load_All_Cargo(planet_id, cargo_item_type, "Drone", unit_group_id)
          // Debug output
          call Sys_Debug_Print("Planets", "    - Recovered Drones")
        endif
        exitwhen (unit_group_index >= unit_group_count)
      endloop
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Scrap_Obsolete_Units
//------------------------------------------------------------------------
function Scrap_Obsolete_Units returns boolean
params
  planet_id:                 long
begin
vars
  sys_loc:                   long
  cargo_item_count:          long
  cargo_index:               long := 0
  cargo_item_id:             long
  cargo_item_design_id:      long
  cargo_item_unit_type:      string
  design_age:                long
  max_scrap_amt:             long := 0
  max_planet_scrap_amt:      long := 0
  scrap_count:               long := 0
  scrap_chance:              long := 0
  scrap_units:               boolean := FALSE
  planet_scrap_count:        long := 0
begin

  // Get our planet's details
  set sys_loc := Sys_Get_Space_Object_System_Location(planet_id)

  // Don't scrap too many units at once in our defense locations
  if (lst_AI_Defense_Location_System.indexof(sys_loc) > 0) then
    set max_scrap_amt := Sys_Divide_Long(lng_Max_Units_To_Scrap, 2)
    set max_planet_scrap_amt := 50
  else
    set max_scrap_amt := lng_Max_Units_To_Scrap
    set max_planet_scrap_amt := 100
  endif

  // Check our planet's cargo for obsolete units and scrap them
  set cargo_item_count := Sys_Get_Space_Object_Cargo_Item_Count(planet_id)
  if (cargo_item_count > 0) then
    loop
      set cargo_index := cargo_index + 1
      set cargo_item_id := Sys_Get_Space_Object_Cargo_Item_ID(planet_id, cargo_index)
      set cargo_item_design_id := Sys_Get_Space_Object_Cargo_Item_Design_ID(planet_id, cargo_item_id)
      set cargo_item_unit_type := Sys_Get_Space_Object_Cargo_Item_Unit_Type(planet_id, cargo_item_id)
      set design_age := sys_long_Game_Date - Sys_Get_Vehicle_Design_Creation_Date(sys_long_Player_ID, cargo_item_design_id)

      // Only check cargo items that are units
      if (cargo_item_unit_type <> "") then
        // Don't consider obsolete status if we need to scrap units immediately
        if (lng_Emergency_Scrap_Pts >= 3) then
          set scrap_units := TRUE
          set scrap_chance := 5 * lng_Emergency_Scrap_Pts * Sys_Divide_Long(design_age, 10)
        else
          if Sys_Is_Vehicle_Design_Obsolete(cargo_item_design_id) then
            if (design_age > lng_Unit_Obsolete_Time_To_Scrap) then
              set scrap_units := TRUE
              set scrap_chance := 5 * Sys_Divide_Long(design_age, 10)
            endif
          else
            set scrap_units := FALSE
          endif
        endif

        if (scrap_units) and (scrap_chance > Sys_Get_Random_Long(1, 100)) and (design_age <> sys_long_Game_Date) then
          // Scrap the cargo item
          call Sys_Space_Object_Scrap_Cargo(planet_id, cargo_item_id)
          set cargo_item_count := cargo_item_count - 1
          set cargo_index := cargo_index - 1

          if (cargo_item_unit_type = "Weapon Platform") then
            set scrap_count := scrap_count + 50
            set planet_scrap_count := planet_scrap_count + 50
          endif
          if (cargo_item_unit_type = "Satellite") then
            set scrap_count := scrap_count + 20
            set planet_scrap_count := planet_scrap_count + 20
          endif
          if (cargo_item_unit_type = "Fighter") or (cargo_item_unit_type = "Troop") then
            set scrap_count := scrap_count + 5
            set planet_scrap_count := planet_scrap_count + 5
          endif
          if (cargo_item_unit_type = "Mine") then
            set scrap_count := scrap_count + 1
            set planet_scrap_count := planet_scrap_count + 1
          endif
        endif
      endif

      exitwhen (cargo_item_count <= 0) or (cargo_index >= cargo_item_count) or (scrap_count >= max_scrap_amt) or (planet_scrap_count >= max_planet_scrap_amt)
    endloop
  endif

  // Debug output
  if (scrap_count > 0) then
    call Sys_Debug_Print("Planets", "    - Scrapped units (" + cargo_item_unit_type + ")")
  endif

  return TRUE
end

// ------------------------------------------------------------------------